package clang.ops;

import clang.data.Expression;
import clang.data.VarType;
import clang.data.Variable;

public class CUnaryOperators {
	public static Variable perform(String opcode, Expression v1) throws Exception
	{
		if("!".equals(opcode)) return performNot(v1.calculate());
		if("++x".equals(opcode)) return performPreInc(v1.calculate());
		if("--x".equals(opcode)) return performPreDec(v1.calculate());
		if("x++".equals(opcode)) return performPostInc(v1.calculate());
		if("x--".equals(opcode)) return performPostDec(v1.calculate());
		if("&".equals(opcode)) return performRef(v1.calculate());
		if("*".equals(opcode)) return performDeref(v1.calculate());
		
		throw new Exception("Unknown unary operator!");
	}
	
	public static Variable performNot(Variable v1) throws Exception
	{
		return new Variable(VarType.INT, v1.getBool() ? 0.0 : 1.0);
	}
	
	public static Variable performPreInc(Variable v1) throws Exception
	{
		v1.setData(v1.getData() + 1.0);
		return new Variable(v1.getType(), v1.getData());
	}
	
	public static Variable performPreDec(Variable v1) throws Exception
	{
		v1.setData(v1.getData() - 1.0);
		return new Variable(v1.getType(), v1.getData());
	}
	
	public static Variable performPostInc(Variable v1) throws Exception
	{
		double oldVal = v1.getData();
		v1.setData(v1.getData() + 1.0);
		return new Variable(v1.getType(), oldVal);
	}
	
	public static Variable performPostDec(Variable v1) throws Exception
	{
		double oldVal = v1.getData();
		v1.setData(v1.getData() - 1.0);
		return new Variable(v1.getType(), oldVal);
	}
	
	public static Variable performRef(Variable v1) throws Exception
	{
		return v1.getAddressVar();
	}
	
	public static Variable performDeref(Variable v1) throws Exception
	{
		return Variable.getValueAtVar(v1.getInteger());
	}
}
